package com.bcx.wind.workflow.imp.cmd.repositorycmd.windprocesscmd;

import com.bcx.wind.workflow.core.flow.NodeModel;
import com.bcx.wind.workflow.core.flow.TaskModel;
import com.bcx.wind.workflow.core.flow.node.ProcessModel;
import com.bcx.wind.workflow.entity.WindProcess;
import com.bcx.wind.workflow.entity.WindProcessConfig;
import com.bcx.wind.workflow.errorcontext.WindError;
import com.bcx.wind.workflow.imp.Configuration;
import com.bcx.wind.workflow.interceptor.Command;
import com.bcx.wind.workflow.interceptor.CommandContext;
import com.bcx.wind.workflow.parser.ProcessBuilder;
import com.bcx.wind.workflow.parser.ProcessBuilderFactory;
import com.bcx.wind.workflow.support.ObjectHelper;
import com.bcx.wind.workflow.support.TimeHelper;

import java.util.List;

import static com.bcx.wind.workflow.core.constant.Constant.ARRAY_NULL;
import static com.bcx.wind.workflow.core.constant.Constant.JSON_NULL;
import static com.bcx.wind.workflow.core.constant.ProcessStatus.RELEASE;
import static com.bcx.wind.workflow.core.constant.ProcessStatus.TEMPLATE;
import static com.bcx.wind.workflow.message.ErrorCode.DATABASE_OPERATE_ERROR;
import static com.bcx.wind.workflow.message.ErrorCode.PROCESS_QUERY_NULL;
import static com.bcx.wind.workflow.message.ErrorCode.PROCESS_RELEASE_STATUS_ERROR;

/**
 * 发布流程定义
 *
 * @author zhanglei
 */
public class ReleaseProcessCommand implements Command<Integer> {

    /**
     * 流程定义ID
     */
    private String processId;

    /**
     * 执行数据
     */
    private CommandContext commandContext;


    /**
     * 流程定义
     */
    private WindProcess windProcess;


    /**
     * 流程定义对象
     */
    private ProcessModel processModel;

    public ReleaseProcessCommand(String processId){
        this.processId = processId;
    }

    @Override
    public Integer executor(CommandContext context) {
        try{
            this.commandContext = context;
            return execute();
        }catch (Exception e){
            e.printStackTrace();
        }
        return 0;
    }

    private Integer execute(){
        //查询
        queryProcess();
        //校验状态
        checkProcessStatus();
        //更新状态
        int ret = changeStatus();
        //构建流程定义对象
        buildProcessModel();
        //添加实施配置数据
        addProcessConfig();
        //添加流程定义缓存
        addProcessModelToCache();
        return ret;
    }

    private void addProcessModelToCache(){
        Configuration configuration = this.commandContext.getConfiguration();
        configuration.addProcessCache(this.windProcess);
    }


    private  void  addProcessConfig(){
        List<NodeModel> taskModels = this.processModel.getAllTaskNodes();
        buildConfig(this.processModel);
        for(NodeModel nodeModel : taskModels){
            buildConfig(nodeModel);
        }
    }


    private  void  buildConfig(NodeModel nodeModel){
        WindProcessConfig config =  new WindProcessConfig()
                .setId(ObjectHelper.primaryKey())
                .setProcessId(this.processId)
                .setConfigName(this.windProcess.getProcessName())
                .setProcessName(this.windProcess.getProcessName())
                .setNodeId(nodeModel.nodeId())
                .setCondition(ARRAY_NULL)
                .setNodeConfig(JSON_NULL)
                .setApproveUser(ARRAY_NULL)
                .setBusinessConfig(JSON_NULL)
                .setSort(1)
                .setLevel(2)
                .setCreateTime(TimeHelper.nowDate());
        int ret = this.commandContext.access().insertProcessConfig(config);
        if(ret != 1){
            WindError.error(DATABASE_OPERATE_ERROR,null);
        }
        this.commandContext.getConfiguration().addProcessConfigCache(processId,config);
    }

    /**
     * 构建流程定义对象
     */
    private  void  buildProcessModel(){
        ProcessBuilder builder = ProcessBuilderFactory.getBuilder(this.windProcess.getContent());
        builder.buildProcess(this.processId);
        this.processModel = builder.getProcessModel();
        this.windProcess.processModel(processModel);
    }


    /**
     * 更新状态
     */
    private  int   changeStatus(){
        this.windProcess.setStatus(RELEASE);
        int ret = this.commandContext.access().updateProcess(this.windProcess);
        if(ret != 1){
            WindError.error(DATABASE_OPERATE_ERROR,null);
        }
        return ret;
    }


    /**
     * 查询
     */
    private  void  queryProcess(){
        this.windProcess = this.commandContext.access().getProcessDefinitionById(this.processId);
        if(this.windProcess == null){
            WindError.error(PROCESS_QUERY_NULL,null,this.processId);
        }
    }

    /**
     * 校验状态是否正确
     */
    private  void checkProcessStatus(){
        String status = this.windProcess.getStatus();
        if(!TEMPLATE.equals(status)){
            WindError.error(PROCESS_RELEASE_STATUS_ERROR,null);
        }
    }


}
